package com.spaceobj.chess.validator;

import org.springframework.stereotype.Component;

import com.spaceobj.chess.entity.GameState;
import com.spaceobj.chess.entity.Move;

@Component
public class MoveValidator {
    
    // 棋盘大小
    private static final int BOARD_WIDTH = 9;
    private static final int BOARD_HEIGHT = 10;
    
    // 棋子类型
    private static final char KING = 'K';    // 将/帅
    private static final char ADVISOR = 'A'; // 士/仕
    private static final char ELEPHANT = 'E';// 象/相
    private static final char HORSE = 'H';   // 马
    private static final char CHARIOT = 'R'; // 车
    private static final char CANNON = 'C';  // 炮
    private static final char PAWN = 'P';    // 兵/卒

    /**
     * 验证走棋是否合法
     * @param gameState 当前游戏状态
     * @param move 走棋操作
     * @return 是否合法
     */
    public boolean validateMove(GameState gameState, Move move) {
        // 1. 基本验证
        if (!validateBasicRules(gameState, move)) {
            return false;
        }

        // 2. 根据棋子类型验证具体规则
        char piece = getPieceAtPosition(gameState.getBoardState(), move.getFromX(), move.getFromY());
        switch (piece) {
            case KING:
                return validateKingMove(gameState, move);
            case ADVISOR:
                return validateAdvisorMove(gameState, move);
            case ELEPHANT:
                return validateElephantMove(gameState, move);
            case HORSE:
                return validateHorseMove(gameState, move);
            case CHARIOT:
                return validateChariotMove(gameState, move);
            case CANNON:
                return validateCannonMove(gameState, move);
            case PAWN:
                return validatePawnMove(gameState, move);
            default:
                return false;
        }
    }

    /**
     * 基本规则验证
     */
    private boolean validateBasicRules(GameState gameState, Move move) {
        // 1. 验证坐标是否在棋盘范围内
        if (move.getFromX() < 0 || move.getFromX() >= BOARD_WIDTH ||
            move.getFromY() < 0 || move.getFromY() >= BOARD_HEIGHT ||
            move.getToX() < 0 || move.getToX() >= BOARD_WIDTH ||
            move.getToY() < 0 || move.getToY() >= BOARD_HEIGHT) {
            return false;
        }

        // 2. 验证起始位置是否有棋子
        char piece = getPieceAtPosition(gameState.getBoardState(), move.getFromX(), move.getFromY());
        if (piece == '0') {
            return false;
        }

        // 3. 验证目标位置是否是己方棋子
        char targetPiece = getPieceAtPosition(gameState.getBoardState(), move.getToX(), move.getToY());
        if (isSameSide(piece, targetPiece)) {
            return false;
        }

        // 4. 验证是否轮到该玩家走棋
        return isPlayerTurn(gameState, piece);
    }

    /**
     * 验证将/帅的走法
     */
    private boolean validateKingMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否在九宫格内
        if (!isInPalace(fromX, fromY, gameState.getCurrentTurn()) ||
            !isInPalace(toX, toY, gameState.getCurrentTurn())) {
            return false;
        }

        // 2. 验证是否只移动一格
        return Math.abs(toX - fromX) + Math.abs(toY - fromY) == 1;
    }

    /**
     * 验证士/仕的走法
     */
    private boolean validateAdvisorMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否在九宫格内
        if (!isInPalace(fromX, fromY, gameState.getCurrentTurn()) ||
            !isInPalace(toX, toY, gameState.getCurrentTurn())) {
            return false;
        }

        // 2. 验证是否斜着走一格
        return Math.abs(toX - fromX) == 1 && Math.abs(toY - fromY) == 1;
    }

    /**
     * 验证象/相的走法
     */
    private boolean validateElephantMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否过河
        if (gameState.getCurrentTurn() == 1 && toY > 4 ||
            gameState.getCurrentTurn() == 2 && toY < 5) {
            return false;
        }

        // 2. 验证是否走"田"字
        if (Math.abs(toX - fromX) != 2 || Math.abs(toY - fromY) != 2) {
            return false;
        }

        // 3. 验证象眼是否被堵
        int eyeX = (fromX + toX) / 2;
        int eyeY = (fromY + toY) / 2;
        return getPieceAtPosition(gameState.getBoardState(), eyeX, eyeY) == '0';
    }

    /**
     * 验证马的走法
     */
    private boolean validateHorseMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否走"日"字
        int deltaX = Math.abs(toX - fromX);
        int deltaY = Math.abs(toY - fromY);
        if (!((deltaX == 2 && deltaY == 1) || (deltaX == 1 && deltaY == 2))) {
            return false;
        }

        // 2. 验证马腿是否被堵
        int legX = fromX + (toX - fromX) / Math.max(deltaX, 1);
        int legY = fromY + (toY - fromY) / Math.max(deltaY, 1);
        return getPieceAtPosition(gameState.getBoardState(), legX, legY) == '0';
    }

    /**
     * 验证车的走法
     */
    private boolean validateChariotMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否直线移动
        if (fromX != toX && fromY != toY) {
            return false;
        }

        // 2. 验证路径上是否有其他棋子
        return isPathClear(gameState, fromX, fromY, toX, toY);
    }

    /**
     * 验证炮的走法
     */
    private boolean validateCannonMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        // 1. 验证是否直线移动
        if (fromX != toX && fromY != toY) {
            return false;
        }

        // 2. 验证路径上的棋子数量
        int pieceCount = countPiecesInPath(gameState, fromX, fromY, toX, toY);
        char targetPiece = getPieceAtPosition(gameState.getBoardState(), toX, toY);
        
        // 如果目标位置有棋子，必须翻过一个棋子
        // 如果目标位置没有棋子，路径必须完全清空
        return (targetPiece != '0' && pieceCount == 1) || 
               (targetPiece == '0' && pieceCount == 0);
    }

    /**
     * 验证兵/卒的走法
     */
    private boolean validatePawnMove(GameState gameState, Move move) {
        int fromX = move.getFromX();
        int fromY = move.getFromY();
        int toX = move.getToX();
        int toY = move.getToY();

        int direction = gameState.getCurrentTurn() == 1 ? 1 : -1;
        boolean isCrossedRiver = (gameState.getCurrentTurn() == 1 && fromY > 4) ||
                               (gameState.getCurrentTurn() == 2 && fromY < 5);

        // 1. 验证是否只能向前移动
        if ((toY - fromY) * direction <= 0) {
            return false;
        }

        // 2. 未过河只能向前移动一格
        if (!isCrossedRiver) {
            return Math.abs(toX - fromX) == 0 && (toY - fromY) * direction == 1;
        }

        // 3. 过河后可以左右移动，但每次只能移动一格
        return (Math.abs(toX - fromX) == 1 && toY == fromY) ||
               (Math.abs(toY - fromY) * direction == 1 && toX == fromX);
    }

    /**
     * 判断是否在九宫格内
     */
    private boolean isInPalace(int x, int y, int player) {
        if (player == 1) {
            return x >= 3 && x <= 5 && y >= 0 && y <= 2;
        } else {
            return x >= 3 && x <= 5 && y >= 7 && y <= 9;
        }
    }

    /**
     * 判断是否是同一方的棋子
     */
    private boolean isSameSide(char piece1, char piece2) {
        if (piece1 == '0' || piece2 == '0') {
            return false;
        }
        return (piece1 >= 'A' && piece1 <= 'Z') == (piece2 >= 'A' && piece2 <= 'Z');
    }

    /**
     * 判断是否轮到该玩家走棋
     */
    private boolean isPlayerTurn(GameState gameState, char piece) {
        boolean isRed = piece >= 'A' && piece <= 'Z';
        return (gameState.getCurrentTurn() == 1) == isRed;
    }

    /**
     * 获取指定位置的棋子
     */
    private char getPieceAtPosition(String boardState, int x, int y) {
        int index = y * BOARD_WIDTH + x;
        return boardState.charAt(index);
    }

    /**
     * 检查路径是否清空
     */
    private boolean isPathClear(GameState gameState, int fromX, int fromY, int toX, int toY) {
        if (fromX == toX) {
            // 垂直移动
            int start = Math.min(fromY, toY) + 1;
            int end = Math.max(fromY, toY);
            for (int y = start; y < end; y++) {
                if (getPieceAtPosition(gameState.getBoardState(), fromX, y) != '0') {
                    return false;
                }
            }
        } else {
            // 水平移动
            int start = Math.min(fromX, toX) + 1;
            int end = Math.max(fromX, toX);
            for (int x = start; x < end; x++) {
                if (getPieceAtPosition(gameState.getBoardState(), x, fromY) != '0') {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 计算路径上的棋子数量
     */
    private int countPiecesInPath(GameState gameState, int fromX, int fromY, int toX, int toY) {
        int count = 0;
        if (fromX == toX) {
            // 垂直移动
            int start = Math.min(fromY, toY) + 1;
            int end = Math.max(fromY, toY);
            for (int y = start; y < end; y++) {
                if (getPieceAtPosition(gameState.getBoardState(), fromX, y) != '0') {
                    count++;
                }
            }
        } else {
            // 水平移动
            int start = Math.min(fromX, toX) + 1;
            int end = Math.max(fromX, toX);
            for (int x = start; x < end; x++) {
                if (getPieceAtPosition(gameState.getBoardState(), x, fromY) != '0') {
                    count++;
                }
            }
        }
        return count;
    }
} 